package com.mhkj.revise.keyPlan.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.mhkj.revise.keyPlan.repository.KeyPlanNodeRepository;
import com.mhkj.revise.keyPlan.service.KeyPlanNodeService;
import com.mhkj.revise.keyPlan.service.KeyPlanService;
import com.mhkj.revise.plan.entity.Plan;
import com.mhkj.revise.plan.entity.PlanNode;
import com.mhkj.revise.plan.repository.PlanNodeRepository;
import com.mics.core.common.componet.Pagination;
import com.mics.core.common.exception.ErrorCode;
import com.mics.core.common.exception.ParamException;
import com.mics.core.common.util.DateUtils;
import com.mics.core.system.base.service.impl.BaseServiceImpl;
import com.mics.core.system.organizational.bean.Company;
import com.mics.core.system.organizational.bean.Office;
import com.mics.core.system.organizational.bean.Post;
import com.mics.core.system.organizational.service.OrgService;

/**
 * 关键节点计划服务
 * @author mics
 * @date 2018年8月16日
 * @version 1.0
 */
@Service
public class KeyPlanNodeServiceImpl extends BaseServiceImpl<PlanNode> implements KeyPlanNodeService{
	@Resource
	private KeyPlanService keyPlanService;
	@Resource
	private KeyPlanNodeRepository keyPlanNodeRepository;
	@Resource
	private OrgService orgService;
	@Resource
	public void setPlanNodeRepository(PlanNodeRepository planNodeRepository) {
		super.setBaseRepository(planNodeRepository);
	}



	/**
	 * 推算周期准备
	 */
	@Override
	@Transactional
	public void calsDealinePrepare(long planId) {
		//寻找初始节点
		Plan plan = keyPlanService.getById(planId);
		List<PlanNode> planNodes = keyPlanNodeRepository.getPlanNodeByPlanId(planId);
		PlanNode root = null;
		for(PlanNode planNode:planNodes){
			if(planNode.getDeadlineDesc().equals("开始")){
				planNode.setBeginDate(plan.getBeginDate());
				planNode.setEndDate(DateUtils.addDay(plan.getBeginDate(), planNode.getDeadline()));
				edit(planNode);
				root = planNode;
				break;
			}
		}
		if(root == null){
			throw new ParamException(ErrorCode.PARAM_ERROR, "没找到开始节点");
		}
		//周期重排
		List<PlanNode> newPlanNodes = new ArrayList<PlanNode>();
		List<PlanNode> childrens = new ArrayList<PlanNode>();
		childrens.add(root);
		newPlanNodes.add(root);
		resetPlanNodeByDeadlineDes(planNodes,childrens,newPlanNodes,1);
		//推算周期
		calsDealine(newPlanNodes);
		//寻找完成时间最大得节点
		PlanNode lastPlanNode = keyPlanNodeRepository.getLastPlanNode(planId);
		plan.setEndDate(lastPlanNode.getEndDate());
		keyPlanService.edit(plan);
	}
	
	
	
	/**
	 * 推算周期
	 * @author mics
	 * @date 2018年8月14日
	 * @version 1.0
	 */
	private void calsDealine(List<PlanNode> newPlanNodes) {
		for(PlanNode planNode:newPlanNodes){
			for(PlanNode planNodeTemp:newPlanNodes){
				if(planNodeTemp.getDeadlineDesc().equals("开始")){
					continue;
				}
				String deadlineDes = planNodeTemp.getDeadlineDesc();
				String[] array = deadlineDes.split("\\|");
				String nameGet = array[0];
				int deadl = Integer.valueOf(array[1]);
				String condition = array[2];
				if(planNode.getNodeName().equals(nameGet)){
					if(condition.equals("之后")){
						Date beginDate = DateUtils.addDay(planNode.getEndDate(),deadl);
						planNodeTemp.setBeginDate(beginDate);
						planNodeTemp.setEndDate(DateUtils.addDay(beginDate, planNodeTemp.getDeadline()));
					}else if(condition.equals("之内")){ 
						Date beginDate = DateUtils.subDay(DateUtils.addDay(planNode.getEndDate(), deadl),planNodeTemp.getDeadline());
						planNodeTemp.setBeginDate(beginDate);
						planNodeTemp.setEndDate(DateUtils.addDay(beginDate, planNodeTemp.getDeadline()));
					}else if(condition.equals("之前")){
						Date date = DateUtils.subDay(planNode.getBeginDate(), deadl);
						planNodeTemp.setBeginDate(date);
						planNodeTemp.setEndDate(DateUtils.addDay(date, planNodeTemp.getDeadline()));
					}
					edit(planNodeTemp);
				}
			}
		}    
	}


	/**
	 * 周期重排
	 * @author mics
	 * @date 2018年8月13日
	 * @version 1.0
	 */
	public void resetPlanNodeByDeadlineDes(List<PlanNode> planNodes,List<PlanNode> childrens,List<PlanNode> newPlanNodes,int count){
		List<PlanNode> results = new ArrayList<PlanNode>();
		for(PlanNode planNode:childrens){
			List<PlanNode> childrenTmeps = new ArrayList<PlanNode>();
			childrenTmeps = searchAfterNode(planNodes,planNode);
			if(childrenTmeps.size() > 0){
				results.addAll(childrenTmeps);
			}
		}
		childrens.clear();
		childrens.addAll(results);
		newPlanNodes.addAll(results);
		if(childrens.size() ==0){
			return;
		}
		if(count < 1000){
			count++;
			resetPlanNodeByDeadlineDes(planNodes,childrens,newPlanNodes,count);
		}else{
			throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "模板周期设定错误");
		}
	}
	
	/**
	 * 搜索下级节点
	 * @author mics
	 * @date 2018年8月13日
	 * @version 1.0
	 */
	public List<PlanNode> searchAfterNode(List<PlanNode> planNodes,PlanNode planNode){
		List<PlanNode> planNodes2 = new ArrayList<PlanNode>();
		for(PlanNode planNodeTemp :planNodes){
			String deadLineDesc = planNodeTemp.getDeadlineDesc();
			String[] array = deadLineDesc.split("\\|");
			if(planNode.getNodeName().equals(array[0])){
				planNodes2.add(planNodeTemp);
			}
		}
		return planNodes2;
	}



	@Override
	public Pagination<PlanNode> listByPage(PlanNode planNode, int pageIndex,
			int pageSize) {
		Specification<PlanNode> spec = new Specification<PlanNode> () {  
			private static final long serialVersionUID = -786003485941679959L;
			@Override
			public Predicate toPredicate(Root<PlanNode> root, CriteriaQuery<?> query,
					CriteriaBuilder criteriaBuilder) {
              List<Predicate> lstPredicates = new ArrayList<Predicate>();
              if(!StringUtils.isEmpty(planNode.getNodeName())){
                  Predicate p1=criteriaBuilder.like(root.get("name").as(String.class), "%"+planNode.getNodeName()+"%");
                  lstPredicates.add(p1);
              }
              if(planNode.getPlan() != null){
                  Join<Object, Object> planType = root.join("plan",JoinType.INNER);
                  Predicate p1=criteriaBuilder.equal(planType.get("id").as(Long.class), planNode.getPlan().getId());
                  lstPredicates.add(p1);
              }
              Predicate[] arrayPredicates = new Predicate[lstPredicates.size() ];
              return criteriaBuilder.and(lstPredicates.toArray(arrayPredicates));
	        }
		};
		Page<PlanNode> pageT =  keyPlanNodeRepository.findAll(spec, PageRequest.of(pageIndex, pageSize, Sort.Direction.ASC,"id"));
		Pagination<PlanNode> pagination = new Pagination<PlanNode>();
		pagination.setTotal(keyPlanNodeRepository.count(spec));
		List<PlanNode> plans = pageT.getContent();
		for(PlanNode planNode2 : plans){
			Company company = orgService.getCompanyById(planNode2.getCompanyId());
			planNode2.setCompanyName(company.getCompanyname());
			Office cOffice = orgService.officeInfo(planNode2.getOfficeId());
			planNode2.setOfficeName(cOffice.getName());
			Post post = orgService.getRoleInfo(planNode2.getPostId());
			planNode2.setPostName(post.getName());
		}
		pagination.setData(plans);
		return pagination;
	}


}
